package mysql

import (
	"context"
	"go.uber.org/zap"
	"gorm.io/gorm"
	log "maya-service/collector/logger"
	"maya-service/config"
	"maya-service/model"
	"maya-service/model/entity"
)

var AiConsult = &aiConsult{}

type aiConsult struct{}

func init() {
	Register(AiConsult)
}

func (a *aiConsult) Init() {
	if config.Conf.AutoMigrate {
		p := &entity.AiConsult{}
		if db.Migrator().HasTable(p) {
			log.Debug("table already exist: ", zap.String("table", p.TableName()))
			return
		}
		if err := db.AutoMigrate(p); err != nil {
			log.Error("filed to create table please check config or manually create", zap.String("table", p.TableName()), zap.String("err", err.Error()))
		} else {
			log.Info("create table successfully", zap.String("table", p.TableName()))
		}
	}
}

// Create
func (a *aiConsult) Create(ctx context.Context, m *entity.AiConsult) (int64, error) {
	err := GetDB(ctx).Create(m).Error
	return m.Id, err
}

// Find detail
func (a *aiConsult) Find(ctx context.Context, in *model.AiConsultInfoRequest) (*entity.AiConsult, error) {
	e := &entity.AiConsult{}

	q := GetDB(ctx).Model(&entity.AiConsult{})
	if in.Id > 0 {
		err := q.Where("id = ?", in.Id).First(&e).Error
		return e, err
	}

	if in.UserId != nil {
		q = q.Where("user_id = ?", in.UserId)
	}

	if in.QuestionId != nil {
		q = q.Where("question_id = ?", in.QuestionId)
	}

	err := q.First(&e).Error
	return e, err

}

// Update
func (a *aiConsult) Update(ctx context.Context, in *model.AiConsultUpdateRequest, dict map[string]interface{}) error {
	if len(in.Ids) > 0 {
		return GetDB(ctx).Model(&entity.AiConsult{}).Where("id in ?", in.Ids).Updates(dict).Error
	}
	return GetDB(ctx).Model(&entity.AiConsult{}).Where("id = ?", in.Id).Updates(dict).Error
}

// Delete
func (a *aiConsult) Delete(ctx context.Context, id int64) error {
	return GetDB(ctx).Delete(&entity.AiConsult{}, id).Error
}

// List query list
func (a *aiConsult) List(ctx context.Context, in *model.AiConsultListRequest) (int, []*entity.AiConsult, error) {
	var (
		q          = GetDB(ctx).Model(&entity.AiConsult{})
		err        error
		total      int64
		aiConsults []*entity.AiConsult
	)

	if in.UserId != nil && in.SupervisorId == nil {

		q = q.Where("user_id = ?", in.UserId)

	}

	if in.Level != nil {

		q = q.Where("level = ?", in.Level)

	}

	if in.Module != nil {

		q = q.Where("module = ?", in.Module)

	}

	if in.Content != nil {

		q = q.Where("content like ?", in.Content)

	}

	if in.ExtraContent != nil {

		q = q.Where("extra_content like ?", in.ExtraContent)

	}

	if in.UserFlag != nil {

		q = q.Where("user_flag = ?", in.UserFlag)

	}

	if in.LeaveMessage != nil {

		q = q.Where("leave_message like ?", in.LeaveMessage)

	}

	if in.LeaveMessageRsp != nil {

		q = q.Where("leave_message_rsp like ?", in.LeaveMessageRsp)

	}

	if in.LeaveMessageFlag != nil {

		q = q.Where("leave_message_flag = ?", in.LeaveMessageFlag)

	}

	if in.IsUnHandler {
		q = q.Where("scores = ? or leave_message_flag=?", 0, "0")
	}

	if in.Scores != nil {

		q = q.Where("scores = ?", in.Scores)

	}

	if in.EvalTime != nil {

		q = q.Where("eval_time = ?", in.EvalTime)

	}

	if in.SupervisorId != nil {

		q = q.Where("supervisor_id = ?", in.SupervisorId)

	}

	if in.SupervisorName != nil {

		q = q.Where("supervisor_name like ?", in.SupervisorName)

	}

	if in.EvalContent != nil {

		q = q.Where("eval_content like ?", in.EvalContent)

	}

	if in.CreatedAt != nil {

		q = q.Where("created_at = ?", in.CreatedAt)

	}

	if in.UpdatedAt != nil {

		q = q.Where("updated_at = ?", in.UpdatedAt)

	}

	// 待处理
	if in.IsSupervisorPending {
		q = q.Where("leave_message_flag = '0' or user_flag = 0")
	}

	// 已处理
	if in.IsSupervisorProcessed {
		q = q.Where("(leave_message_flag = '' and user_flag = 1) or (leave_message_flag = '1' and user_flag = 1)")
	}

	if in.GteScores != nil {
		q = q.Where("scores > ?", 0)
	}

	if err = q.Count(&total).Error; err != nil {
		return 0, nil, err
	}
	if err = q.Order("created_at desc").Limit(in.Size).Offset((in.Index - 1) * in.Size).Find(&aiConsults).Error; err != nil {
		return 0, nil, err
	}
	return int(total), aiConsults, nil
}

// ExecTransaction execute database transaction
func (a *aiConsult) ExecTransaction(ctx context.Context, callback func(ctx context.Context) error) error {
	return GetDB(ctx).Transaction(func(tx *gorm.DB) error {
		ctx = context.WithValue(ctx, ContextTxKey, tx)
		return callback(ctx)
	})
}
